<?php

defined('SYSPATH') or die('Access error!');

class Core_Mailer
{

    //Swift_Mailer 对象
    protected $_mailer = null;

    //邮件类型
    protected $type = null;

    protected $from = null;

    protected $to = null;

    /**
     * CC
     * @var string
     */
    protected $cc = null;

    /**
     * BCC
     * @var string
     */
    protected $bcc = null;

    protected $subject = null;

    protected $data = null;

    protected $attachments = null;

    protected $batch_send = false;

    protected $message = null;

    protected $config = "default";

    protected $debug = FALSE;

    // Mailer 的一些方法名
    protected $method = NULL;

    public static $instances = array();

    //发送的邮件模板
    protected $view = array(
        'html' => null,
        'text' => null,
    );

    public function before()
    {
    }

    public function after()
    {
    }

    public function __construct($config = "default")
    {
        if (!class_exists('Swift', FALSE))
        {
            require_once Core::find_file('vendor', 'swift/swift_required');
        }
        $this->before();
    }

    
    public static function instance($config = "default")
    {
        if (!isset(self::$instances[$config]))
        {
            self::$instances[$config] = new Mailer;
        }
        return self::$instances[$config]->config($config);
    }

   /**
    *  连接服务器
    * @param type $config
    * @return type\
    */
    public function connect($config = "default")
    {
        $config = Core::config('mailer.' . $config);

        $transport = ( is_null($config['transport']) ) ? 'native' : $config['transport'];
        $config = $config['options'];

        $klass = 'Mailer_Transport_' . ucfirst($transport);
        $factory = new $klass();

        return $this->_mailer = Swift_Mailer::newInstance($factory->build($config));
    }

   /**
    * 需要调用的方法集合
    * @param type $name
    * @param type $args
    * @return Core_Mailer
    * @throws Exception
    */
    public function __call($name, $args = array())
    {
        $pattern = '/^(type|from|to|cc|bcc|subject|data|attachments|batch_send|config|html|text|debug)$/i';
        if (isset($args[0]) && is_array($args[0]))
        {
            foreach ($args[0] as $key => $value)
            {
                if (preg_match($pattern, $key))
                {
                    $this->$key = $value;
                }
            }
        }

        if (preg_match($pattern, $name))
        {
            $this->$name = $args[0];
            return $this;
        }

        if (preg_match('/^sen(d|t)_/i', $name))
        {
            $method = substr($name, 5, strlen($name));

            if (method_exists($this, $method))
            {
                call_user_func_array(array($this, $method), $args);

                $this->setup($method);

                return $this->send();
            }
            else
            {
                throw new Exception('Method: ' . $method . ' does not exist.');
            }
        }
    }

    /**
     * 初始化swift
     * @param type $method
     * @return \Core_Mailer\
     */
    public function setup($method = NULL)
    {
        $this->message = Swift_Message::newInstance();
        $this->message->setSubject($this->subject);
        $is_html = isset($this->html);
        $is_text = isset($this->text);

        if ($is_html || $is_text)
        {
            if ($is_html)
            {
                $this->view["html"] = $this->html;
                $this->message->setBody($this->view['html'], 'text/html');
            }
            if ($is_text)
            {
                $this->view["text"] = $this->text;
                if ($is_html)
                {
                    $this->message->addPart($this->view['text'], 'text/plain');
                }
                else
                {
                    $this->message->setBody($this->view['text'], 'text/plain');
                }
            }
        }
        else
        {
            // 邮件模板
            $template = strtolower(preg_replace('/_/', '/', get_class($this)) . "/{$method}");
            $text = View::factory($template);
            $this->set_data($text);
            $this->view['text'] = $text->render();

            if ($this->type === 'html')
            {
                $template = View::factory($template . "_text");
                $this->set_data($template);
                $this->view['html'] = $this->view['text'];
                $this->view['text'] = $template->render();

                $this->message->setBody($this->view['html'], 'text/html');
                $this->message->addPart($this->view['text'], 'text/plain');
            }
            else
            {
                $this->message->setBody($this->view['text'], 'text/plain');
            }
        }

        if ($this->attachments !== null)
        {
            if (!is_array($this->attachments))
            {
                $this->attachments = array($this->attachments);
            }

            foreach ($this->attachments as $file)
            {
                $this->message->attach(Swift_Attachment::fromPath($file));
            }
        }

        // to
        if (!is_array($this->to))
        {
            $this->to = array($this->to);
        }
        $this->message->setTo($this->to);

        // cc
        if ($this->cc !== null)
        {
            if (!is_array($this->cc))
            {
                $this->cc = array($this->cc);
            }
            $this->message->setCc($this->cc);
        }

        // bcc
        if ($this->bcc !== null)
        {
            if (!is_array($this->bcc))
            {
                $this->bcc = array($this->bcc);
            }
            $this->message->setBcc($this->bcc);
        }

        // from
        $this->message->setFrom($this->from);

        return $this;
    }

    /**
     *  发送邮件
     * @return boolean
     * @throws Core_Exception
     */
    public function send()
    {
        if ($this->message === NULL)
        {
            $this->setup();
        };

        $this->connect($this->config);

        try
        {
            if (!$this->batch_send)
            {
                $this->result = $this->_mailer->send($this->message);
            }
            else
            {
                $this->result = $this->_mailer->batchSend($this->message);
            }
        } catch (Exception $e)
        {
            return false;
            if (self::$debug)
            {
                throw new Core_Exception('Server is not responding');
            }
            else
            {
                return false;
            };
        };

        $this->after();
        return $this->result;
    }

    /**
     * 给模板设置变量
     *
     * @param &View
     * @return &View
     */
    protected function set_data(& $view)
    {
        if ($this->data != null)
        {
            if (!is_array($this->data))
            {
                $this->data = array($this->data);
            };

            foreach ($this->data as $key => $value)
            {
                $view->bind($key, $this->data[$key]);
            }
        }
        return $view;
    }

}

